#include <iostream>
#include <type_traits>

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_float.hpp>
template <class T, class Enable = void>
class data_processor {
public:
	double process(const T& v1, const T& v2, const T& v3)
	{
		std::cout << "Generic version" << std::endl;
		return 1.1;
	}
};

template <class T>
class data_processor<T, typename boost::enable_if_c<boost::is_integral<T>::value>::type>
{
public:
	double process(const T& v1, const T& v2, const T& v3)
	{
		std::cout << "integral version" << std::endl;
		return v1 + v2 + v3;
	}
};

template <class T>
class data_processor<T, typename boost::enable_if_c<boost::is_float<T>::value>::type>
{
public:
	double process(const T& v1, const T& v2, const T& v3)
	{
		std::cout << "float version" << std::endl;
		return v1 + v2 + v3;
	}
};

template <class T>
double example_func(T v1, T v2, T v3) {
	data_processor<T> proc;
	return proc.process(v1, v2, v3);
}

template <class T>
typename std::enable_if<boost::is_float<T>::value, T>::type
test(T param)
{
	std::cout << "test float version" << std::endl;
	return param;
}

template <class T>
typename std::enable_if<boost::is_integral<T>::value, T>::type
test(T param)
{
	std::cout << "test integral version" << std::endl;
	return param;
}

int main() {
	example_func(1, 2, 3);
	short s = 0;
	example_func(s, s, s);

	example_func(1.0, 2.0, 3.0);
	example_func(1.0f, 2.0f, 3.0f);

	example_func("Hello", "word", "processing");

	double a = 1.1;
	int b = 1;
	test(a);
	test(b);
	return 0;
}